/**
 * @program: smart-school
 * @description: 报告接口层
 * @author: Qing Miao Dan Xie
 * @create: 2022-05-31 10:36
 **/
package org.jeecg.modules.analysisachievement.reports.controller;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.util.PoitlIOUtils;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.analysisachievement.achclasses.vo.AchClassAchievementExamScoreVo;
import org.jeecg.modules.analysisachievement.reports.service.AnalysisReportService;
import org.jeecg.modules.classes.entity.CouClass;
import org.jeecg.modules.classes.service.ICouClassService;
import org.jeecg.modules.common.api.ISysInfo;
import org.jeecg.modules.common.baseentity.BaseApiEntity;
import org.jeecg.modules.student.service.IStuStudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Api(tags = "v_ach_student_subject_score")
@RestController
@RequestMapping("/analysisachievement/achstudent/report")
@Slf4j
public class ReportController {

    @Autowired
    private AnalysisReportService analysisReportService;

    @Autowired
    private ISysBaseAPI sysBaseAPI;
    @Autowired
    private ISysInfo sysInfo;

    @Autowired
    private ICouClassService couClassService;
    @Autowired
    private IStuStudentService stuStudentService;

    @GetMapping("/poi-report")
    public void generateReport(AchClassAchievementExamScoreVo achClassAchievementExamScoreVo,String downloadOrPreview, HttpServletRequest req, HttpServletResponse response) throws NoSuchFieldException, IllegalAccessException, IOException {
        //组装vo以外的其他参数
        Map<String,String> queryParam = sysInfo.getMapQueryParamByReq(req);
        //获取当前登录用户信息 把租户 部门 身份 学期 学年等基本信息信息赋值克隆给achClassAchievementExamScoreVo
        BaseApiEntity baseApiEntity = sysInfo.querySysInfoCloneObj(req,achClassAchievementExamScoreVo,false); //获取当前登录用户信息 把租户 部门 身份 学期 学年等基本信息信息赋值给vo

        //根据用户身份重新设置查询条件值，不同的用户身份查询过滤不同的数据：
        //1.获取用户身份 userIdentity loginUser.getUserIdentity() 用户身份字典码user_identity， 3教师 4学生 5家长 6班级  1普通用户 2上级部门负责人
        //2.获取用户id loginUser.getId()
        //userIdentity 用户身份字典码user_identity， 3教师 4学生 5家长 6班级  1普通用户 2上级部门负责人
        achClassAchievementExamScoreVo = reSetObjectValue(baseApiEntity, achClassAchievementExamScoreVo);


        String templateModelId = ""; // templatePath =  templateModelId.getFilePath(), 根据模板id设置模板文件路径：从数据库字典码中配置或从模板表中配置
            XWPFTemplate template = analysisReportService.PoiGenerator(templateModelId,achClassAchievementExamScoreVo, parseQueryParam(achClassAchievementExamScoreVo, req), response);
        //输出到网络流
        //下载或预览标识 downloadOrPreview "download"=下载  "preview"=预览 "save“=保存到服务器，不允许为空
        downloadOrPreview = oConvertUtils.isEmpty(downloadOrPreview) ? "save" : downloadOrPreview;
        try {
            // 允许跨域
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setCharacterEncoding("UTF-8"); //指定编码格式

            if("download".equals(downloadOrPreview.toLowerCase())) {
//                    response.setContentType("application/x-download"); //下载
//                    response.setContentType("application/octet-stream"); //预览
                response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); //下载
//                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); //下载

                // 设置response的Header，注意这句，如果开启，默认浏览器会进行下载操作，如果注释掉，浏览器会默认预览
                String filename = "out_template.docx";
                response.addHeader("Content-Disposition", "attachment;filename=" + filename);
            }
            else if("preview".equals(downloadOrPreview.toLowerCase())){
                response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); //预览
            }
            else if("save".equals(downloadOrPreview.toLowerCase())){
                //保存到服务器 // 输出到文件流：保存到服务器指定路径下
                template.write(new FileOutputStream("output.docx"));
            }

            //输出到流：把template输出到response输出流
            OutputStream out = response.getOutputStream();
            BufferedOutputStream bos = new BufferedOutputStream(out);
            template.write(bos);
            bos.flush();
            out.flush();
            PoitlIOUtils.closeQuietlyMulti(template, bos, out);
        }
                    catch (IOException e) {
            e.printStackTrace();
        }




        // response.getOutputStream().write(bos.toByteArray());

//
////        1、设置ContentType //不同的文件类型，contentType不一样，比如图片一般是image/jpeg、image/png等
//        response.setContentType("application/x-download");
////        2、设置文件名，并指定编码格式
//
//        fileName = URLEncoder.encode("浏览器要显示的文件名", "UTF-8"); // 设置编码
//        response.setCharacterEncoding("UTF-8");
////        3、将文件名addHeader
//        response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
//
//        try {
//            InputStream stream = new FileInputStream(file);
//
//            ServletOutputStream out = response.getOutputStream();
//
//            byte buff[] = new byte[1024];
//
//            int length = 0;
//
//            while ((length = stream.read(buff)) > 0) {
//                out.write(buff,0,length);
//
//            }
//
//            stream.close();
//
//            out.close();
//
//            out.flush();
//
//        } catch (IOException e) {
//            e.printStackTrace();
//
//        }
    }

    private Map<String, String> parseQueryParam(AchClassAchievementExamScoreVo achClassAchievementExamScoreVo, HttpServletRequest req) {
        //组装vo以外的其他参数
        Map<String, String[]> queryParamArray = req.getParameterMap();
        Map<String, String> queryParam = new HashMap<String, String>();
        for (Map.Entry<String, String[]> entry : queryParamArray.entrySet()) {
            //不知道为什么，传入参数自带**，需替换
            String queryParamValue = entry.getValue()[0];
            queryParamValue = queryParamValue.replace("*", "");
            if (entry.getValue().length == 0 || "".equals(entry.getValue()[0])) {
                continue;
            } else {
                queryParam.put(entry.getKey(), queryParamValue);
            }

        }
        //获取当前登录用户信息
        String token = req.getHeader(CommonConstant.X_ACCESS_TOKEN);
        String username = JwtUtil.getUsername(token);
        //		SysUser sysUser = sysUserService.getOneUser(username);// sysBaseAPI.getUserByName(username); 不能直接引用system模块，需使用APi调用
        LoginUser loginUser = sysBaseAPI.getUserByName(username); //.getUserById() 获取登录用户
        String tenantId = req.getHeader("tenant-id");//获取当前登录用户的租户id
        String sysOrgCode = loginUser.getOrgCode();//获取当前用户的当前的部门编码（不是id是编码）,该编码随前端切换
        String departId = sysBaseAPI.getDepartIdsByOrgCode(sysOrgCode);//获取当前用户设置的部门id
        List<String> subDepIdsList = sysBaseAPI.getSubDepIdsByDepId(departId); //获取下级部门的部门id，自定义改造sysBaseAPI
        String subDepSysOrgCodes = sysBaseAPI.getSubDepOrgCodesByDepId(departId); //直接获取下级部门的orgcode，自定义改造sysBaseAPI
        int userIdentity = loginUser.getUserIdentity();//获取当前登录用户身份：字典码 user_identity

        achClassAchievementExamScoreVo.setTenantId(tenantId);
        achClassAchievementExamScoreVo.setSysOrgCode(subDepSysOrgCodes);

        //userIdentity 用户身份字典码user_identity， 3教师 4学生 1普通用户 2上级部门负责人 5家长 6班级
        if (userIdentity == 3 || userIdentity == 1 || userIdentity == 2) {
            achClassAchievementExamScoreVo.setSysOrgCode(subDepSysOrgCodes);
            queryParam.put("sysOrgCode", subDepSysOrgCodes);
        } else if (userIdentity == 4) {
            //学生身份只能查看自己班级的数据
            CouClass couClass = couClassService.getCouClassByUserID(loginUser.getId());
            achClassAchievementExamScoreVo.setClassId(couClass.getId());
        } else if (userIdentity == 5) {
            //家长身份只能查看孩子的数据
            String classIds = loginUser.getId(); //获取家长的孩子的班级id
            achClassAchievementExamScoreVo.setClassId(classIds);
        } else if (userIdentity == 6) {
            //班级身份只能查看自己班级的数据
//			String classId = loginUser.getId();//获取班级id
            CouClass couClass = couClassService.getCouClassByUserID(loginUser.getId());
            achClassAchievementExamScoreVo.setClassId(couClass.getId());
            queryParam.put("classId", couClass.getId());
        } else {
            achClassAchievementExamScoreVo.setSysOrgCode(subDepSysOrgCodes);
            queryParam.put("sysOrgCode", subDepSysOrgCodes);
        }

        return queryParam;
    }
    /**
     *
     * 有需要身份识别的业务需打开下方注释补充查询条件就可以了
     * 根据业务需要设置查询参数，不同身份的用户不同的查询参数、得到不同的查询结果
     * 注意：有些业务并不需要身份识别，有些业务必须识别身份:4学生用户只能查自己的数据不能查别人的，6班级用户只能查自己班级的数据不能查其他班级的数据，
     * 3老师只能查老师所在部门和下级部门的数据，1普通用户（一般是非教学用户）
     * @param baseApiEntity
     * @return Object
     */
    private AchClassAchievementExamScoreVo reSetObjectValue(BaseApiEntity baseApiEntity,AchClassAchievementExamScoreVo achClassAchievementExamScoreVo){
        //1.获取用户身份 userIdentity loginUser.getUserIdentity() 用户身份字典码user_identity， 3教师 4学生 5家长 6班级  1普通用户 2上级部门负责人
        //2.获取用户id loginUser.getId()
        int userIdentity = baseApiEntity.getUserIdentity();//获取当前登录用户身份：字典码 user_identity，3教师 4学生 5家长 6班级  1普通用户 2上级部门负责人
        String userId = baseApiEntity.getLoginUser().getId(); //当前登录用户id

        //有需要身份识别的业务需打开下方注释补充查询条件就可以了
        //根据业务需要设置查询参数，不同身份的用户不同的查询参数、得到不同的查询结果
        //注意：有些业务并不需要身份识别，有些业务必须识别身份:4学生用户只能查自己的数据不能查别人的，6班级用户只能查自己班级的数据不能查其他班级的数据，3老师只能查老师所在部门和下级部门的数据，1普通用户（一般是非教学用户） 2上级部门负责人只能查所在部门和下级部门的数据

        //  //userIdentity 用户身份字典码user_identity， 3教师 4学生 5家长 6班级  1普通用户 2上级部门负责人
        // // 学生、老师、班级、家长，都有绑定用户的user_id字段，可以根据user_id查询到对应的学生、老师、班级 基础档案信息
        if (userIdentity ==4 ){
            //学生身份只能查看自己班级的数据
            CouClass couClass = couClassService.getCouClassByUserID(userId);
            //StuStudent student = stuStudentService.getStuStudentByUserId(userId);
            achClassAchievementExamScoreVo.setClassId(couClass.getId());
            achClassAchievementExamScoreVo.setSysOrgCode(null);
            //当前用户和业务数据可能不在同一个部门，需设置为null，例如：学生张三属于七年级部门，成绩数据在初中教学部
        }
        else if (userIdentity == 5 ){
            //家长身份只能查看孩子的数据，注意一个家长可能有多个孩子 一个孩子属于多个家长
            //家长身份只能查看孩子的数据
            String classIds = userId; //获取家长的孩子的班级id
            achClassAchievementExamScoreVo.setClassId(classIds);
            achClassAchievementExamScoreVo.setSysOrgCode(null); //当前用户和业务数据可能不在同一个部门，需设置为null，例如：家长属于家长部，学生张三属于七年级部门，成绩数据在初中教学部
        }
        else if (userIdentity == 6 ){
            //班级身份只能查看自己班级的数据
//			String classId = loginUser.getId();//获取班级id
            CouClass couClass = couClassService.getCouClassByUserID(userId);
            achClassAchievementExamScoreVo.setClassId(couClass.getId());
            achClassAchievementExamScoreVo.setSysOrgCode(null); //当前用户和业务数据可能不在同一个部门，需设置为null，例如：某班级属于七年级部门，成绩数据在初中教学部
        }
        else if ( userIdentity == 3 ){
            //老师身份，可以查看当前部门和下级子集部门的数据
            //(如果考虑老师只能查看所教授科目、所教授班级学生的数据，则与普通用户有区分，否则是一样的)
            achClassAchievementExamScoreVo.setSysOrgCode(baseApiEntity.getSubDepSysOrgCodes());
        }
        else if ( userIdentity == 3 ){
            //老师身份，可以查看当前部门和下级子集部门的数据
            //考虑老师按照所教授班级的权限查询的话，可以在这里设置
            achClassAchievementExamScoreVo.setSysOrgCode(baseApiEntity.getSubDepSysOrgCodes());
        }
        else if ( userIdentity == 1 || userIdentity == 2 ){
            //普通用户身份、部门负责人（领导），可以查看当前部门和下级子集部门的数据
            achClassAchievementExamScoreVo.setSysOrgCode(baseApiEntity.getSubDepSysOrgCodes());
        }
        else{
            //其他身份或默认设置
            achClassAchievementExamScoreVo.setSysOrgCode(baseApiEntity.getSubDepSysOrgCodes());
        }

        return achClassAchievementExamScoreVo;
    }

}
